iT邦幫忙

2023 iThome 鐵人賽

DAY 23
0
Mobile Development

SwiftUI 男孩系列 第 23

Day 23: Data binding: @State, @Binding, read-only property

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20231008/20130138BMAGKegOkb.jpg
Photo by Sébastien Goldberg on Unsplash
Mount Cook, Nouvelle-Zélande

期望實作這功能
https://ithelp.ithome.com.tw/upload/images/20231008/20130138rZY2gP7m9y.png

RatingView 子視圖會告訴父視圖,Rating 給幾顆星⭐️。

發現之前招式

struct PublicSwimmingPoolDetailView: View {

    var publicSwimmingPool: PoolItem
}

// ------

PublicSwimmingPoolDetailView(publicSwimmingPool: item)

publicSwimmingPool 是 read-only property 🤔


研究一陣子開竅,需要 @Binding 新招式

  1. @State

    • 用於私有狀態管理。

    • 主要用於視圖內部,當狀態變化時,視圖會重新渲染。

    • 是值類型的存儲方式,當值改變時,只有與該值有關的視圖部分會被重新渲染。

    • 例子:

      @State private var isToggled: Bool = false
      
      
  2. @Binding

    • 這是一種參照某個其它狀態的方式。當你需要從一個視圖到另一個視圖共享同一狀態時,這非常有用。

    • 它不擁有該狀態的真實存儲,而是提供一種方式來讀取和寫入該值。

    • 例子:

      @Binding var text: String
      
  3. read-only property

  • 只能被讀取,而不能被重新賦值或修改。
struct ParentView: View {
    @State private var pool = PoolItem(name: "Community Pool")

    var body: some View {
        VStack {
            // ... 其他 UI ...

            PublicSwimmingPoolDetailView(publicSwimmingPool: pool)
        }
    }
}

struct PublicSwimmingPoolDetailView: View {
    var publicSwimmingPool: PoolItem

    var body: some View {
        // ... 使用 publicSwimmingPool ...
    }
}

視覺化解釋
https://ithelp.ithome.com.tw/upload/images/20231008/20130138Z1dl9CpQ0a.png

struct RatingView: View {
    @Binding var rating: Int
    
    var label = ""
    var maximumRating = 5
    
    var offImage: Image?
    var onImage = Image(systemName: "star.fill")
    
    var offColor = Color.gray
    var onColor = Color.yellow
    
    var body: some View {
        HStack {
            if label.isEmpty == false {
                Text(label)
            }
            
            ForEach(1..<maximumRating + 1, id: \.self) { number in
                image(for: number)
                    .resizable()
                    .scaledToFit()
                    .frame(width: 28, height: 28)
                    .foregroundColor(number > rating ? offColor : onColor)
                    .onTapGesture {
                        rating = number
                    }
            }
        }
    }
    
    func image(for number: Int) -> Image {
        if number > rating {
            return offImage ?? onImage
        } else {
            return onImage
        }
    }
}

明天介紹 @ViewBuilder,接續做 FeedBack 功能
https://ithelp.ithome.com.tw/upload/images/20231008/20130138ZYsMZKM4za.png

下集待續


上一篇
Day 22: SwiftUI 有 Grand Central Dispatch ⌚️
下一篇
Day 24: @ViewBuilder
系列文
SwiftUI 男孩30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言